package br.com.sgmf.web.validator;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import org.springframework.stereotype.Component;

@Component("cpfValidator")
public class CPFValidator implements Validator {

	@Override
	public void validate(FacesContext context, UIComponent component,
			Object value) throws ValidatorException {
		value = removeMask(String.valueOf(value));

		if (!validaCPF(String.valueOf(value))) {
			FacesMessage message = new FacesMessage(
					FacesMessage.SEVERITY_ERROR,
					"CPF: Erro de validação: número de CPF inválido", null);
			throw new ValidatorException(message);
		}
	}

	private static String removeMask(String value) {
		String cpf = value;

		if (value != null && !value.equals("")) {
			cpf = value.replaceAll("\\.", "").replaceAll("\\-", "");
		}

		return cpf;
	}

	private static boolean validaCPF(String cpf) {
		if (cpf == null || cpf.length() != 11 || isCPFPadrao(cpf)) {
			return false;
		}

		try {
			Long.parseLong(cpf);
		} catch (NumberFormatException e) {
			e.printStackTrace();
			return false;
		}

		return calcDigVerif(cpf.substring(0, 9)).equals(cpf.substring(9, 11));
	}

	private static boolean isCPFPadrao(String cpf) {
		return cpf.equals("00000000000") || cpf.equals("11111111111")
				|| cpf.equals("22222222222") || cpf.equals("33333333333")
				|| cpf.equals("44444444444") || cpf.equals("55555555555")
				|| cpf.equals("66666666666") || cpf.equals("77777777777")
				|| cpf.equals("88888888888") || cpf.equals("99999999999");

	}

	private static String calcDigVerif(String num) {
		Integer primDig, segDig;
		int soma = 0, peso = 10;

		for (int i = 0; i < num.length(); i++) {
			soma += Integer.parseInt(num.substring(i, i + 1)) * peso--;
		}

		if (soma % 11 == 0 | soma % 11 == 1) {
			primDig = 0;
		} else {
			primDig = 11 - soma % 11;
		}

		soma = 0;
		peso = 11;
		for (int i = 0; i < num.length(); i++) {
			soma += Integer.parseInt(num.substring(i, i + 1)) * peso--;
		}

		soma += primDig * 2;
		if (soma % 11 == 0 | soma % 11 == 1) {
			segDig = 0;
		} else {
			segDig = 11 - soma % 11;
		}

		return primDig.toString() + segDig.toString();
	}

}
